|
CS 116 Tutorial 10 (Solutions): Reading and Writing Files
Reminders:
- Assignment 09 is due on Monday, Dec 2nd at 10:00pm
Tutorial Solutions
class CD:
'''
Fields: artist (Str), duration (Nat), songs (listof Str)
where
* artist is the name of the performer of the album
* duration is the length of the CD in seconds
* songs contains the names of the songs on the CD.
'''
def __init__(self, artist, dur, los):
'''
[purpose]: Initializes a CD
[fields]:
* artist (artist's name) - Str
* duration (duration of CD in seconds) - Nat
* songs (list of artist's songs) - (listof Str)
'''
self.artist = artist
self.duration = dur
self.songs = los
def __repr__(self):
'''
[purpose]: Represents a CD
[format]:
Artist's Name: XXX
Duration: XXX
Songs: XXX
'''
songstr = ""
for song in self.songs:
songstr += song + ", "
songstr = songstr[:-2]
return "Artist Name: {0}\nDuration: {1}\nSongs: {2}".format\
(self.artist, self.duration, songstr)
def __eq__(self, other):
return isinstance(other, CD) \
and self.artist == other.artist \
and self.duration == other.duration \
and self.songs == other.songs
-
Write the Python function make_cd_dict that reads
the data
from a text file and returns a dictionary of CD objects
containing the data from the file, with keys
equal to the name of the CD.
{ album title: CD(artist, duration, [listof songs]) }
- You may assume that each CD has a unique name.
- The files will be formatted in the following way:
name of artist, name of CD, length in seconds, song titles
(separated by a comma and at least one space).
Example File:
Yes, Close to the Edge, 2266, Close to the Edge, And You and I, Siberian Khatru
Various, Disney Mix, 912, You'll Be in My Heart, Kiss the Girl, Circle of Life, I'll Make a Man Out of You, Whole New World, Go the Distance
Pink Floyd, Wish You Were Here (Side 1), 1268, Shine On You Crazy Diamond (1-5), Welcome to the Machine
Jonathan Coulton, Code Monkey, 203, Code Monkey
The Beatles, Abbey Road, 255, Mean Mr. Mustard, Polythene Pam, She Came in Through the Bathroom Window
Solution using readline :
import check
# Dictionaries for testing
d2 = {"The Final Countdown": CD("Europe", 227, ["The Final Countdown"])}
d3 = {"Disney Mix": CD("Various", 912, ["You'll Be in My Heart", "Kiss the Girl",
"Circle of Life", "I'll Make a Man Out of You",
"Whole New World", "Go the Distance"]),
"Code Monkey": CD("Jonathan Coulton", 203, ["Code Monkey"]),
"Close to the Edge": CD("Yes", 2266, ["Close to the Edge", "And You and I", "Siberian Khatru"]),
"Wish You Were Here (Side 1)": CD("Pink Floyd", 1268, ["Shine On You Crazy Diamond (1-5)",
"Welcome to the Machine"]),
"Abbey Road": CD("The Beatles", 255, ["Mean Mr. Mustard",
"Polythene Pam",
"She Came in Through the Bathroom Window"])}
def make_cd_dict(fname):
'''
reads data from a file called fname and outputs a dictionary of CD objects
Effects: reads data from a file and creates a dict of CD objects from
the data
make_cd_dict: Str -> (dictof Str CD)
Examples:
If the file is blank, the function will produce {}
make_cd_list("made_cd_dict_2.txt") => d2
'''
new_dict = {}
f = open(fname, 'r')
line = f.readline()
while line != "":
fields = line.split(",")
cd_fields = list(map(str.strip, fields))
artist = cd_fields[0]
title = cd_fields[1]
dur = int(cd_fields[2])
songs = cd_fields[3:]
new_dict[title] = CD(artist, dur, songs)
line = f.readline()
f.close()
return new_dict
# Blank File
check.expect("Test 1", make_cd_dict("make_cd_dict_1.txt"), {})
# File with one CD
check.expect("Test 2", make_cd_dict("make_cd_dict_2.txt"), d2)
#File with multiple CDs
check.expect("Test 3", make_cd_dict("make_cd_dict_3.txt"), d3)
Solution using readlines :
import check
def make_cd_dict(fname):
'''
reads data from a file called fname and outputs a dictionary
of CD objects
Effects: reads data from a file and creates a dict of CD objects
from the data
make_cd_dict: Str -> (dictof Str CD)
Examples:
If the file is blank, the function will produce {}
make_cd_list("made_cd_dict_2.txt") => d2
'''
f = open(fname, 'r')
data = f.readlines()
f.close()
new_dict = {}
for cd in data:
fields = cd.split(",")
cd_fields = list(map(str.strip, fields))
artist = cd_fields[0]
title = cd_fields[1]
dur = int(cd_fields[2])
songs = cd_fields[3:]
new_dict[title] = CD(artist, dur, songs)
return new_dict
# Blank File
check.expect("Test 1", make_cd_dict("make_cd_dict_1.txt"), {})
# File with one CD
check.expect("Test 2", make_cd_dict("make_cd_dict_2.txt"), d2)
#File with multiple CDs
check.expect("Test 3", make_cd_dict("make_cd_dict_3.txt"), d3)
-
Write the Python function output_CD_info that
consumes a dictionary of
CD objects (like the one returned in Q1) and a string.
If the string is not a key in the dictionary, the function
should do nothing.
If the string is a key in the dictionary, the function should
create a text file named
"Artist - Title".txt , where Artist and Title relate
to the cd found at
cd_dict[name] .
The text file should contain (each on its own line):
- the title of the CD in uppercase,
- then the artist,
- then the duration of the CD (formatted like in question 1),
- then a blank line, and
- then the index of the song with name of each track in the
CD.
d = {"Disney Mix": CD("Various", 912, ["You'll Be in My Heart", "Kiss the Girl",
"Circle of Life", "I'll Make a Man Out of You",
"Whole New World", "Go the Distance"])}
For example, output_CD_info(d, "Disney Mix") would
create a file named
"Various - Disney Mix.txt" containing:
DISNEY MIX
Various
912
1. You'll Be in My Heart
2. Kiss the Girl
3. Circle of Life
4. I'll Make a Man Out of You
5. Whole New World
6. Go the Distance
Solution with write:
import check
# Dictionaries for testing
d2 = {"The Final Countdown": CD("Europe", 227, ["The Final Countdown"])}
d3 = {"Disney Mix": CD("Various", 912, ["You'll Be in My Heart", "Kiss the Girl",
"Circle of Life", "I'll Make a Man Out of You",
"Whole New World", "Go the Distance"]),
"Code Monkey": CD("Jonathan Coulton", 203, ["Code Monkey"]),
"Close to the Edge": CD("Yes", 2266, ["Close to the Edge", "And You and I", "Siberian Khatru"]),
"Wish You Were Here (Side 1)": CD("Pink Floyd", 1268, ["Shine On You Crazy Diamond (1-5)",
"Welcome to the Machine"]),
"Abbey Road": CD("The Beatles", 255, ["Mean Mr. Mustard",
"Polythene Pam",
"She Came in Through the Bathroom Window"])}
def output_CD_info(cd_dict, name):
'''
writes the data from the CD object associated with that name to
a new file named "Artist - Title.txt" if name is a key in cd_dict.
Effects: writes a file if name is in cd_dict
output_CD_info: (dictof Str CD) Str -> None
Examples:
output_CD_info(d2, "The Final Countdown") will create a file called
"Europe - The Final Countdown.txt" with THE FINAL COUNTDOWN on its first
line, Europe on its second line, 227 sec on the third line, a blank fourth
line, and 1. The Final Countdown on its fifth (and final) line
output_CD_info(d3, "Disney Mix") will create a file called "Various - Disney Mix.txt"
with DISNEY MIX on its first line, Various on its second line, 912 sec on the third
line, a blank fourth line, and a list of tracks on the following line in the form: 3.
Circle of Life
'''
if name in cd_dict:
cd = cd_dict[name]
else:
return None
filename = "{0} - {1}.txt".format(cd.artist, name)
f = open(filename, 'w')
f.write("{0}\n".format(name.upper()))
f.write("{0}\n".format(cd.artist))
f.write("{0} sec\n".format(cd.duration))
f.write("\n")
for i in range(len(cd.songs)):
f.write("{0}. {1}\n".format(i+1, cd.songs[i]))
f.close()
# TESTING:
check.expect("Test 1", output_CD_info({}, "Aquarium"), None)
check.expect("Test 2", output_CD_info(d3, "Aquarium"), None)
# No file was created by the previous two tests
check.set_file_exact("Europe - The Final Countdown.txt","output_CD_info_3.txt")
check.expect("Test 3", output_CD_info(d2, "The Final Countdown"), None)
check.set_file_exact("The Beatles - Abbey Road.txt","output_CD_info_4.txt")
check.expect("Test 4", output_CD_info(d3, "Abbey Road"), None)
Solution with writelines:
import check
# Dictionaries for testing
d2 = {"The Final Countdown": CD("Europe", 227, ["The Final Countdown"])}
d3 = {"Disney Mix": CD("Various", 912, ["You'll Be in My Heart", "Kiss the Girl",
"Circle of Life", "I'll Make a Man Out of You",
"Whole New World", "Go the Distance"]),
"Code Monkey": CD("Jonathan Coulton", 203, ["Code Monkey"]),
"Close to the Edge": CD("Yes", 2266, ["Close to the Edge", "And You and I", "Siberian Khatru"]),
"Wish You Were Here (Side 1)": CD("Pink Floyd", 1268, ["Shine On You Crazy Diamond (1-5)",
"Welcome to the Machine"]),
"Abbey Road": CD("The Beatles", 255, ["Mean Mr. Mustard",
"Polythene Pam",
"She Came in Through the Bathroom Window"])}
def output_CD_info(cd_dict, name):
'''
writes the data from the CD object associated with that name to a
new file named "artist - title.txt" if name is a key in cd_dict.
Effects: writes a file if name is in cd_dict
output_CD_info: (dictof Str CD) Str -> None
Examples:
output_CD_info(d2, "The Final Countdown") will create a file called
"Europe - The Final Countdown.txt" with THE FINAL COUNTDOWN on its first
line, Europe on its second line, 227 sec on the third line, a blank fourth
line, and 1. The Final Countdown on its fifth (and final) line
output_CD_info(d3, "Disney Mix") will create a file called "Various - Disney Mix.txt"
with DISNEY MIX on its first line, Various on its second line, 912 sec on the
third line, a blank fourth line, and a list of tracks on the following line
in the form: 3. Circle of Life
'''
if name in cd_dict:
cd = cd_dict[name]
else:
return None
filename = "{0} - {1}.txt".format(cd.artist, name)
output = ["{0}\n".format(name.upper()),
"{0}\n".format(cd.artist),
"{0} sec\n".format(cd.duration),
"\n"]
for i in range(len(cd.songs)):
output.append("{0}. {1}\n".format(i+1, cd.songs[i]))
f = open(filename, 'w')
f.writelines(output)
f.close()
# TESTING:
check.expect("Test 1", output_CD_info({}, "Aquarium"), None)
check.expect("Test 2", output_CD_info(d3, "Aquarium"), None)
# No file was created by the previous two tests
check.set_file_exact("Europe - The Final Countdown.txt","output_CD_info_3.txt")
check.expect("Test 3", output_CD_info(d2, "The Final Countdown"), None)
check.set_file_exact("The Beatles - Abbey Road.txt","output_CD_info_4.txt")
check.expect("Test 4", output_CD_info(d3, "Abbey Road"), None)
|